package com.everydayflash.flar.mustang {
	import com.as3dmod.util.XMath;
	import com.everydayflash.math.Vector2;
	
	import flash.display.InteractiveObject;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.ui.Keyboard;	

	/**
	 * @author bartekd
	 */
	public class Driver {

		private var input:InteractiveObject;
		private var car:ICar;
		
		private var _speed:Number;
		private var _orientation:Number;
		public var _carAngle:Number;
		
		public var movingForward:Boolean = false;
		public var movingBackward:Boolean = false;
		public var handBrake:Boolean = false;
		public var turnAmount:Number = 0;
		private var FRICTION:Number = 0.96;		private var ACCELERATION:Number = 0.16;		private var MAX_SPEED:Number = 5;		private var turningLeft:Boolean = false;
		private var turningRight:Boolean = false;

		public function Driver(input:InteractiveObject, car:ICar) {
			_speed = 0;
			_orientation = 0;			_carAngle = 0;
			
			this.car = car;
			this.input = input;
			
			input.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
			input.addEventListener(KeyboardEvent.KEY_UP, onKeyUp);			input.addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
		
		private function onEnterFrame(event:Event):void {
			if(movingForward && !handBrake) _speed += ACCELERATION;
			
			if(movingBackward && !handBrake) {
				if(speed > 0.1) _speed *= .92;
				else _speed -= ACCELERATION / 8;
			}

			var vt:Number = turnAmount * (Math.sqrt(velocity) * XMath.sign(_speed, 1) ) / (10 + velocity * 3);
			if(handBrake) vt *= 2;
			
			if(velocity < .5) vt *= (velocity * 2);
			
			_orientation -= vt;
			
			if(!handBrake) _carAngle = _orientation;
			
			if(turningLeft) {
				turnAmount += 0.05;
				turnAmount = XMath.trim(-car.MAX_TURN, car.MAX_TURN, turnAmount);
			} else if(turningRight) {
				turnAmount -= 0.05;
				turnAmount = XMath.trim(-car.MAX_TURN, car.MAX_TURN, turnAmount);
			} else {
				if(!handBrake) turnAmount *= 0.9;
			}
			
//			if(handBrake) Log.info(_carAngle + " : " + _orientation);
			
			if(velocity > 0.01) _speed *= FRICTION;
			else _speed = 0;
			
			_speed = Math.min(MAX_SPEED, _speed);
		}

		public function get brake():Boolean {
			return movingBackward && speed > 0;
		}
		
		private function onKeyDown(event:KeyboardEvent):void {
			switch(event.keyCode) {
				case Keyboard.UP:
					movingForward = true;
					break;
				case Keyboard.DOWN:
					movingBackward = true;
					break;
				case Keyboard.LEFT:
					turningLeft = true;
					break;
				case Keyboard.RIGHT:
					turningRight = true;
					break;
				case Keyboard.SPACE:				case Keyboard.CONTROL:
					if(Math.abs(_speed) > 2) handBrake = true;
					break;
			}
		}

		private function onKeyUp(event:KeyboardEvent):void {
			switch(event.keyCode) {
				case Keyboard.UP:
					movingForward = false;
					break;
				case Keyboard.DOWN:
					movingBackward = false;
					break;
				case Keyboard.LEFT:
					turningLeft = false;
					break;
				case Keyboard.RIGHT:
					turningRight = false;
					break;
				case Keyboard.SPACE:
				case Keyboard.CONTROL:
					movingForward = false;
					movingBackward = false;
					if(handBrake) {
						var h:Number = Math.abs(_carAngle - _orientation) % (Math.PI / 2);
						if(h > Math.PI / 4) _speed *= -1;
						_speed *= .5;
					}
					handBrake = false;
					break;
			}
		}
		
		public function get moveAmount():Vector2 {
			return Vector2.create(_speed, _carAngle);
		}
		
		public function get direction():Number {
			return XMath.sign(_speed, 0);
		}				public function get speed():Number {
			return _speed;		}
		
		public function set speed(s:Number):void {
			_speed = s;
		}
		
		public function get velocity():Number {
			return Math.abs(_speed);
		}				public function get orientation():Number {
			return _orientation;		}
	}
}
